package org.jsola.hr.common;

import com.alibaba.fastjson.JSON;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.jsola.common.StrKit;
import org.jsola.core.Result;
import org.jsola.exception.ParamException;
import org.jsola.file.constant.FileConstants;
import org.jsola.hr.constant.HrConstants;
import org.jsola.hr.dto.EmpPaperContractAddDTO;
import org.jsola.hr.dto.UpdateEmpFieldDTO;
import org.jsola.hr.entity.CompanyAdditionalFieldsDO;
import org.jsola.hr.entity.EmpInfoDO;
import org.jsola.hr.provider.IFileProviderService;
import org.jsola.hr.service.*;
import org.jsola.user.core.TokenUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpMethod;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.awt.*;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.List;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

/**
 * 导入花名册附件
 *
 * @author wcl
 */
@Slf4j
@RestController("hrImportEmpFileController")
@RequestMapping(HrConstants.API_PATH + "/v1/importEmpFile")
public class ImportEmpFile {
    /**
     * 本地文件夹地址
     */
    private static final String LOCAL_FILE_PATH = "C:\\Users\\Administrator\\Desktop\\新建文件夹";

    /**
     * 本地文件夹地址
     */
    private static final String LOCAL_FILE_PATH_2 = "C:\\Users\\lvyon\\Desktop\\新建文件夹\\合同";

    /**
     * 本地文件夹地址
     */
    private static final String LOCAL_FILE_PATH_3 = "C:\\Users\\lvyon\\Desktop\\新建文件夹\\材料附件";

    @Autowired
    private IEmpInfoService empInfoService;

    @Autowired
    private IFileProviderService fileProviderService;

    @Autowired
    private IEmpPaperContractService empPaperContractService;

    @Autowired
    private IEmpInfoExtraService empInfoExtraService;

    @Autowired
    private ICompanyNecessaryFieldService companyNecessaryFieldService;

    @Autowired
    private ICompanyAdditionalFieldsService companyAdditionalFieldsService;

    /**
     * 导入花名册附件(亚一明昊)
     */
    @GetMapping("/importEmpFile")
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public Result<String> importEmpFile() {
        // 手动构建token
        TokenUser tokenUser = new TokenUser("20220425uploadFile", "5BBF35BA8A9D42C299FE43B99E4FCFA9");
        // 读取文件, 格式：文件夹-身份证命名的文件夹-文件
        File file = new File(LOCAL_FILE_PATH);
        long l1 = System.currentTimeMillis();
        // *本次运行项目，数量太多会中断运行，建议100个文件作为一组，手动在文件夹分开，一组大约耗时六分钟左右
        List<FileModel> fileList = getFile(file);
        long l2 = System.currentTimeMillis();
        log.info("读取文件==》共：{}个文件，耗时：{}ms", fileList.size(), (l2 - l1));
        if (CollectionUtils.isEmpty(fileList)) {
            log.error("指定目录下没有文件");
            return Result.fail("指定目录下没有文件");
        }
        // 文件名-文件 Map
        Map<String, List<FileModel>> nameFileMap = fileList.stream().collect(Collectors.groupingBy(FileModel::getIdCard));

        // 读取身份证（文件名为身份证号）
        List<String> idCards = fileList.parallelStream().map(FileModel::getIdCard).distinct().collect(Collectors.toList());

        // 用身份证查询员工
        List<EmpInfoDO> empInfoDOList = empInfoService.listByIdCardList(idCards, tokenUser);
        log.info("共：{}员工", empInfoDOList.size());
        List<String> idCardList = empInfoDOList.parallelStream().map(EmpInfoDO::getIdCard).collect(Collectors.toList());
        // 身份证-EmpInfoVO Map
        Map<String, List<EmpInfoDO>> idCardEmpInfoMap = empInfoDOList.parallelStream()
                .collect(Collectors.groupingBy(EmpInfoDO::getIdCard));
        int count = 0;
        int empNullCount = 0;
        int fileNullCount = 0;
        List<String> errorList = new ArrayList<>();
        for (String idCard : idCardList) {
            List<EmpInfoDO> empInfoList = idCardEmpInfoMap.get(idCard);
            List<FileModel> fileModels = nameFileMap.get(idCard);
            if (!CollectionUtils.isEmpty(empInfoList) && !org.springframework.util.CollectionUtils.isEmpty(fileModels)) {
                for (EmpInfoDO empInfoVO : empInfoList) {
                    // 身份证照片
                    List<String> urlList1 = new ArrayList<>();
                    // 合同附件
                    List<String> urlList2 = new ArrayList<>();
                    // 将原始数据和本次导入数据做拼接
                    if (StrKit.isNotEmpty(empInfoVO.getAnnexPersonPhoto())) {
                        urlList1.add(empInfoVO.getAnnexPersonPhoto());
                    }
                    if (StrKit.isNotEmpty(empInfoVO.getAnnexLaborContract())) {
                        urlList2.add(empInfoVO.getAnnexLaborContract());
                    }
                    // 身份证照片
                    List<File> uploadFileList1 = new ArrayList<>();
                    // 合同附件
                    List<File> uploadFileList2 = new ArrayList<>();
                    for (FileModel fileModelItem : fileModels) {
                        File file1 = fileModelItem.getFile();
                        if (file1.getName().contains("合同附件")) {
                            uploadFileList2.add(file1);
                        } else {
                            uploadFileList1.add(file1);
                        }
                    }
                    List<String> uploadUrlList1 = fileProviderService.batchSiteUpload(uploadFileList1, FileConstants.DOWNLOAD_TYPE_INLINE, tokenUser);
                    List<String> uploadUrlList2 = fileProviderService.batchSiteUpload(uploadFileList2, FileConstants.DOWNLOAD_TYPE_INLINE, tokenUser);
                    urlList1.addAll(uploadUrlList1);
                    urlList2.addAll(uploadUrlList2);
                    if (CollectionUtils.isEmpty(urlList1) && CollectionUtils.isEmpty(urlList2)) {
                        continue;
                    }
                    EmpInfoDO empInfoDO = new EmpInfoDO();
                    empInfoDO.setId(empInfoVO.getId());
                    empInfoDO.setAnnexPersonPhoto(String.join(",", urlList1));
                    empInfoDO.setAnnexLaborContract(String.join(",", urlList2));
                    // 更新信息
                    empInfoService.updateByIdSelective(empInfoDO, empInfoVO.getSiteId(), "20220425uploadFile");
                    count++;
                    log.info("正在上传第--》" + (count) + "个");
                }
            } else {
                if (CollectionUtils.isEmpty(empInfoList)) {
                    empNullCount++;
                    log.info("员工为空：" + (empNullCount));
                } else {
                    fileNullCount++;
                    log.info("文件为空：" + (fileNullCount));
                }
                errorList.add(idCard);
            }
        }

        long l3 = System.currentTimeMillis();
        log.info("上传材料附件耗时：{}ms", (l3 - l1));
        log.info("错误身份证列表-----》" + JSON.toJSONString(errorList));
        log.info("======》上传结束,成功：" + count + "个，员工为空：" + empNullCount + "个，文件为空：" + fileNullCount + "个");
        return Result.success("======》上传结束,成功：" + count + "个，员工为空：" + empNullCount + "个，文件为空：" + fileNullCount + "个");
    }

    /**
     * 导入纸质合同(四川贝诺)
     */
    @GetMapping("/importContractSCBN")
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public Result<String> importContract() {
        // 手动构建token
        TokenUser tokenUser = new TokenUser("20230112uploadFile", "8F5101D8322346338D03CF4F78A43B30");
        // 本地文件夹
        File file = new File(LOCAL_FILE_PATH_2);
        File[] files = file.listFiles();
        assert files != null;
        // 文件夹内的合同<手机号, 对应的合同列表>
        Map<String, List<File>> contractFileMap = new HashMap<>(2048);
        // 文件夹内的手机号列表
        List<String> phoneList = new ArrayList<>();
        for (File contractFile : files) {
            // 文件夹内的合同名称 呋ビ橥缈萍加邢拊鹑喂纠投贤琠艾少文_2022年03月02日_18186188008 是这种玩意
            // 没法截取员工姓名只能截取手机号 所以这里用手机号去匹配empInfo表
            String fileName = contractFile.getName();
            String[] fileNameArray = fileName.split("_");
            String phone = fileNameArray[fileNameArray.length - 1];
            // 这么截取出来后面还有.pdf的后缀要把后缀也截掉
            phone = phone.split("\\.")[0];
            List<File> phoneContractList = contractFileMap.get(phone);
            if (CollectionUtils.isEmpty(phoneContractList)) {
                phoneContractList = new ArrayList<>();
                phoneContractList.add(contractFile);
            } else {
                phoneContractList.add(contractFile);
            }
            contractFileMap.put(phone, phoneContractList);
            if (!phoneList.contains(phone)) {
                phoneList.add(phone);
            }
        }
        // 用手机号查询员工
        List<EmpInfoDO> empList = empInfoService.selectByPhonesAndSiteId(phoneList, "8F5101D8322346338D03CF4F78A43B30");
        Map<String, EmpInfoDO> empMap = empList.stream().collect(Collectors.toMap(EmpInfoDO::getPhone, v -> v));
        for (String phone : empMap.keySet()) {
            EmpInfoDO empInfo = empMap.get(phone);
            List<File> empContractFile = contractFileMap.get(phone);
            for (File uploadFile : empContractFile) {
                List<String> urlList = fileProviderService.batchSiteUpload(Collections.singletonList(uploadFile), FileConstants.DOWNLOAD_TYPE_INLINE, tokenUser);
                String url = urlList.get(0);
                EmpPaperContractAddDTO empPaperContract = new EmpPaperContractAddDTO();
                empPaperContract.setCompanyId(empInfo.getCompanyId());
                empPaperContract.setEmpId(empInfo.getId());
                empPaperContract.setFile(url);
                empPaperContract.setName(uploadFile.getName());
                empPaperContract.setTimeLimitType(1);
                empPaperContractService.save(empPaperContract, tokenUser);
            }
        }
        return Result.success();
    }

    /**
     * 导入材料附件(四川贝诺)
     */
    @GetMapping("/importMaterialSCBN")
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public Result<String> importMaterial() {
        // 手动构建token
        TokenUser tokenUser = new TokenUser("20230113uploadFile", "8F5101D8322346338D03CF4F78A43B30");
        // 本地文件夹
        File file = new File(LOCAL_FILE_PATH_3);
        File[] files = file.listFiles();
        assert files != null;
        // 文件夹内的合同<员工姓名, 文件列表>
        Map<String, List<File>> materialFileMap = new HashMap<>(8192);
        // 文件夹内的姓名列表
        List<String> empNameList = new ArrayList<>();
        for (File materialFile : files) {
            // 文件夹内的文件名称 3_宋小兰_0   0代表 身份证正面  1代表身份证反面  2代表银行卡正面   3  4  5不知道是啥
            String fileName = materialFile.getName();
            String[] fileNameArray = fileName.split("_");
            String empName = fileNameArray[1];
            // 这么截取出来后面还有.png的后缀要把后缀也截掉
            List<File> empMaterialList = materialFileMap.get(empName);
            if (CollectionUtils.isEmpty(empMaterialList)) {
                empMaterialList = new ArrayList<>();
                empMaterialList.add(materialFile);
            } else {
                empMaterialList.add(materialFile);
            }
            materialFileMap.put(empName, empMaterialList);
            if (!empNameList.contains(empName)) {
                empNameList.add(empName);
            }
        }
        // 用员工姓名查询员工
        List<EmpInfoDO> empList = empInfoExtraService.selectByNamesAndSiteId(empNameList, "8F5101D8322346338D03CF4F78A43B30");
        List<String> companyIdList = empList.stream().map(EmpInfoDO::getCompanyId).distinct().collect(Collectors.toList());
        Map<String, List<EmpInfoDO>> empGroup = empList.stream().collect(Collectors.groupingBy(EmpInfoDO::getName));
        List<CompanyAdditionalFieldsDO> fields = companyAdditionalFieldsService.getByCompanyId(companyIdList, "其他附件资料", "8F5101D8322346338D03CF4F78A43B30");
        Map<String, CompanyAdditionalFieldsDO> fieldMap = fields.stream().collect(Collectors.toMap(CompanyAdditionalFieldsDO::getCompanyId, v -> v));
        for (String empName : empGroup.keySet()) {
            List<EmpInfoDO> empInfoList = empGroup.get(empName);
            List<File> empContractFile = materialFileMap.get(empName);
            for (EmpInfoDO empInfo : empInfoList) {
                List<File> idCard = new ArrayList<>();
                List<File> otherFileList = new ArrayList<>();
                File bankCard = null;
                for (File uploadFile : empContractFile) {
                    String fileName = uploadFile.getName();
                    String[] fileNameArray = fileName.split("_");
                    String index = fileNameArray[2];
                    index = index.split("\\.")[0];
                    if (index.equals("0") || index.equals("1")) {
                        idCard.add(uploadFile);
                    } else if (index.equals("2")) {
                        bankCard = uploadFile;
                    } else {
                        otherFileList.add(uploadFile);
                    }
                }
                List<String> idCardUrl = fileProviderService.batchSiteUpload(idCard, FileConstants.DOWNLOAD_TYPE_INLINE, tokenUser);
                List<String> otherUrl = fileProviderService.batchSiteUpload(otherFileList, FileConstants.DOWNLOAD_TYPE_INLINE, tokenUser);
                String bankUrl = null;
                if (!ObjectUtils.isEmpty(bankCard)) {
                    bankUrl = fileProviderService.siteUpload(bankCard, FileConstants.DOWNLOAD_TYPE_INLINE, tokenUser);
                }
                EmpInfoDO empInfoDO = new EmpInfoDO();
                empInfoDO.setId(empInfo.getId());
                empInfoDO.setAnnexIdCard(String.join(",", idCardUrl));
                empInfoDO.setAnnexSalaryCard(bankUrl);
                empInfoService.updateByIdSelective(empInfoDO, empInfo.getSiteId(), "20230113uploadFile");

                UpdateEmpFieldDTO updateEmpFieldDTO = new UpdateEmpFieldDTO();
                updateEmpFieldDTO.setEmpInfoId(empInfo.getId());
                updateEmpFieldDTO.setCompanyId(empInfo.getCompanyId());
                updateEmpFieldDTO.setModuleCode("annex");
                Map<String, String> data = new HashMap<>(8);
                CompanyAdditionalFieldsDO companyAdditionalFields = fieldMap.get(empInfo.getCompanyId());
                data.put(companyAdditionalFields.getId() + "", String.join(",", otherUrl));
                updateEmpFieldDTO.setData(data);
                companyNecessaryFieldService.updateEmpFieldValue(updateEmpFieldDTO, HttpMethod.PUT, true, tokenUser);
            }
        }
        return Result.success();
    }

    /**
     * 解压zip文件
     */
    private static File unZipFile(String inputFile) throws IOException {
        File srcFile = new File(inputFile);
        String destDirPath = LOCAL_FILE_PATH.replace(".zip", "");
        //创建压缩文件对象
        ZipFile zipFile = new ZipFile(srcFile);
        //开始解压
        Enumeration<?> entries = zipFile.entries();
        while (entries.hasMoreElements()) {
            ZipEntry entry = (ZipEntry) entries.nextElement();
            // 如果是文件夹，就创建个文件夹
            if (entry.isDirectory()) {
                srcFile.mkdirs();
            } else {
                // 如果是文件，就先创建一个文件，然后用io流把内容copy过去
                File targetFile = new File(destDirPath + "/" + entry.getName());
                // 保证这个文件的父文件夹必须要存在
                if (!targetFile.getParentFile().exists()) {
                    targetFile.getParentFile().mkdirs();
                }
                targetFile.createNewFile();
                // 将压缩文件内容写入到这个文件中
                InputStream is = zipFile.getInputStream(entry);
                FileOutputStream fos = new FileOutputStream(targetFile);
                int len;
                byte[] buf = new byte[1024];
                while ((len = is.read(buf)) != -1) {
                    fos.write(buf, 0, len);
                }
                // 关流顺序，先打开的后关闭
                fos.close();
                is.close();
            }
        }
        return null;
    }

    /**
     * 获取指定路径下的文件
     * 格式：文件夹-身份证命名的文件夹-文件
     *
     * @param file 文件
     * @return 本地路径集合
     */
    private List<FileModel> getFile(File file) {
        if (!file.exists()) {
            log.error("指定目录下没有文件");
            throw new ParamException("指定目录下没有文件");
        }
        List<FileModel> fileList = new ArrayList<>();
        // 最外层文件夹目录
        if (file.isDirectory()) {
            File[] fileSeconds = file.listFiles();
            if (Objects.nonNull(fileSeconds)) {
                // 第二层文件夹目录
                for (File fileSecond : fileSeconds) {
                    // 身份证
                    String idCard = fileSecond.getName();
                    if (fileSecond.isDirectory()) {
                        // 最后一层文件
                        File[] filesThirds = fileSecond.listFiles();
                        for (File filesThird : filesThirds) {
                            FileModel fileModel = new FileModel();
                            fileModel.setIdCard(idCard);
                            fileModel.setFile(filesThird);
                            fileList.add(fileModel);
                        }
                    } else {
                        log.error("fileSecond:文件读取类型错误：{}", file.getName());
                    }
                }
            }
        } else if (file.isFile()) {
            log.error("文件读取类型错误：{}", file.getName());
        }
        return fileList;
    }

    /**
     * 文件对象
     */
    @Data
    static class FileModel {
        /**
         * 身份证
         */
        private String idCard;

        /**
         * 文件
         */
        private File file;
    }
}
